package com.yao.mall.service.impl;

import com.yao.mall.model.vo.ShoppingOrderDetailVO;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.yao.mall.model.dto.shoppingOrder.OrderQueryRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yao.mall.common.ErrorCode;
import com.yao.mall.common.UserHolder;
import com.yao.mall.config.BusinessException;
import com.yao.mall.mapper.*;
import com.yao.mall.model.dto.shoppingOrder.GoodsSkuOrderRequest;
import com.yao.mall.model.dto.shoppingOrder.OrderCreateRequest;
import com.yao.mall.model.entity.*;
import com.yao.mall.model.vo.*;
import com.yao.mall.model.vo.perOrder.PreOrderOfCartVO;
import com.yao.mall.model.vo.perOrder.PreOrderOfGoodsSkuVO;
import com.yao.mall.service.*;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;

import static com.yao.mall.constant.RedisConstant.STATUS;

/**
 * @author jiahua.yao
 * @description 针对表【shopping_order】的数据库操作Service实现
 * @date 2024-03-26 19:31:16
 */
@Service
public class ShoppingOrderServiceImpl extends ServiceImpl<ShoppingOrderMapper, ShoppingOrder>
        implements ShoppingOrderService {

    @Resource
    private ShoppingCartMapper shoppingCartMapper;

    @Resource
    private ShoppingCartService shoppingCartService;
    @Resource
    private AddressService addressService;

    @Resource
    private AddressMapper addressMapper;

    @Resource
    private GoodsSkuMapper goodsSkuMapper;

    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private ShoppingOrderMapper shoppingOrderMapper;

    @Resource
    private ShoppingOrderDetailService shoppingOrderDetailService;

    @Resource
    private SkuAttrValueService skuAttrValueService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SkuImageMapper skuImageMapper;

    @Override
    public PreOrderOfCartVO preOrderOfCart() {
        //用户登录信息
        UserVO user = UserHolder.getUser();
        Long id = user.getId();
        PreOrderOfCartVO preShoppingOrderVO = new PreOrderOfCartVO();
        //查询该用户通过购物车页面下单的商品信息
        QueryWrapper<ShoppingCart> shoppingCartQueryWrapper = new QueryWrapper<>();
        shoppingCartQueryWrapper.eq("user_id", id).eq("selected", 1);
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.selectList(shoppingCartQueryWrapper);
        List<ShoppingCartVO> shoppingCartVOList = shoppingCartService.toShoppingCartVO(shoppingCarts);
        preShoppingOrderVO.setShoppingVOList(shoppingCartVOList);
        //获取用户的地址信息
        List<AddressVO> addressVOList = addressService.getAddress();
        preShoppingOrderVO.setAddressVOList(addressVOList);
        //统计订单summary
        SummaryVO summaryVO = new SummaryVO();
        int allCount = 0;
        BigDecimal allTotalPrice = new BigDecimal(0);
        for (ShoppingCart shoppingCart : shoppingCarts) {
            allTotalPrice = allTotalPrice.add(shoppingCart.getTotalPrice());
            allCount += shoppingCart.getQuantity();
        }
        summaryVO.setAllCount(allCount);
        summaryVO.setAllTotalPrice(allTotalPrice);
        summaryVO.setPayPrice(allTotalPrice);
        //邮费暂记为0（包邮费）
        summaryVO.setAllPostage(new BigDecimal(0));
        preShoppingOrderVO.setSummaryVO(summaryVO);
        return preShoppingOrderVO;
    }

    @Override
    public PreOrderOfGoodsSkuVO preOrderOfGoodsSku(GoodsSkuOrderRequest preOrderRequest) {
        Long skuId = preOrderRequest.getSkuId();
        Integer quantity = preOrderRequest.getQuantity();
        if (skuId == null || quantity == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "必要数据为空");
        }
        PreOrderOfGoodsSkuVO preOrderOfGoodsSkuVO = new PreOrderOfGoodsSkuVO();
        //商品信息
        GoodsSku goodsSku = goodsSkuMapper.selectById(skuId);
        ShoppingGoodsVO shoppingGoodsVO = new ShoppingGoodsVO();
        shoppingGoodsVO.setUserId(UserHolder.getUser().getId());
        shoppingGoodsVO.setSkuId(preOrderRequest.getSkuId());
        shoppingGoodsVO.setGoodsName(goodsSku.getGoodsName());
        shoppingGoodsVO.setQuantity(quantity);
        shoppingGoodsVO.setUnitPrice(goodsSku.getSkuPrice());
        BigDecimal allCount = goodsSku.getSkuPrice().multiply(BigDecimal.valueOf(quantity));
        shoppingGoodsVO.setTotalPrice(allCount);
        QueryWrapper<SkuImage> skuImageQueryWrapper = new QueryWrapper<>();
        skuImageQueryWrapper.eq("sku_id", skuId).eq("sort", 0);
        SkuImage skuImage = skuImageMapper.selectOne(skuImageQueryWrapper);
        shoppingGoodsVO.setSkuImage(skuImage.getImage());
        shoppingGoodsVO.setStock(goodsSku.getStock());
        shoppingGoodsVO.setAttrsText(skuAttrValueService.getAttrsText(skuId));
        //便于前端展示，这里虽然只有一件商品，依旧使用list存储
        List<ShoppingGoodsVO> shoppingGoodsVOS = new ArrayList<>();
        shoppingGoodsVOS.add(shoppingGoodsVO);
        preOrderOfGoodsSkuVO.setShoppingVOList(shoppingGoodsVOS);
        //地址信息
        List<AddressVO> addressVOList = addressService.getAddress();
        preOrderOfGoodsSkuVO.setAddressVOList(addressVOList);
        //统计订单summary
        SummaryVO summaryVO = new SummaryVO();
        summaryVO.setAllCount(quantity);
        summaryVO.setAllTotalPrice(allCount);
        summaryVO.setAllPostage(new BigDecimal(0));
        summaryVO.setPayPrice(allCount);
        preOrderOfGoodsSkuVO.setSummaryVO(summaryVO);
        return preOrderOfGoodsSkuVO;
    }


    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public CreateOrderVO createOrder(OrderCreateRequest orderCreateRequest) {
        checkRequest(orderCreateRequest);
        UserVO user = UserHolder.getUser();
        //整体思路，
        // 1、先存订单表
        // 2、订单详情表
        // 3、返回信息设置
        // 4、善后操作：
        // 4.1删除购物车选中数据（如果是通过购物车下单）
        // 4.2 商品库存更新(针对购买的sku）
        ShoppingOrder shoppingOrder = new ShoppingOrder();
        //1.1、地址信息,下单用户，支付类型
        Address address = addressMapper.selectById(orderCreateRequest.getAddressId());
        shoppingOrder.setReceiverName(address.getReceiver());
        shoppingOrder.setReceiverMobile(address.getContact());
        shoppingOrder.setReceiverAddress(address.getFullAddress() + address.getDetailAddress());
        shoppingOrder.setUserId(user.getId());
        shoppingOrder.setPayType(orderCreateRequest.getPayType());
        //1.2、订单状态,创建时设置为1（待支付),冗余字段postage设为0
        shoppingOrder.setPostage(new BigDecimal(0));
        shoppingOrder.setOrderStatus(1);
        //1.3、总价
        BigDecimal totalPrice = new BigDecimal(0);
        //3.1 购买数量初始化
        int totalQuantity = 0;
        //2.1 订单详情list
        List<ShoppingOrderDetail> orderDetails = new ArrayList<>();
        List<GoodsSkuOrderRequest> buyGoodsSkuList = orderCreateRequest.getBuyGoodsSkuList();
        for (GoodsSkuOrderRequest goodsSkuOrderRequest : buyGoodsSkuList) {
            Long skuId = goodsSkuOrderRequest.getSkuId();
            GoodsSku goodsSku = goodsSkuMapper.selectById(skuId);
            //2.2 订单详情的skuId、商品name、商品pic、单价、购买数量、一个sku的购买总价.sku的属性
            ShoppingOrderDetail shoppingOrderDetail = new ShoppingOrderDetail();
            shoppingOrderDetail.setSkuId(skuId);
            Integer quantity = goodsSkuOrderRequest.getQuantity();
            BigDecimal skuTotalPrice = goodsSku.getSkuPrice()
                    .multiply(BigDecimal.valueOf(quantity));
            shoppingOrderDetail.setUnitPrice(goodsSku.getSkuPrice());
            shoppingOrderDetail.setQuantity(quantity);
            shoppingOrderDetail.setSkuTotalPrice(skuTotalPrice);
            orderDetails.add(shoppingOrderDetail);
            Goods goods = goodsMapper.selectById(goodsSku.getSpuId());
            shoppingOrderDetail.setGoodsName(goodsSku.getGoodsName());
            shoppingOrderDetail.setGoodsImage(goods.getMainImage());
            String attrsText = skuAttrValueService.getAttrsText(skuId);
            shoppingOrderDetail.setAttrsText(attrsText);
            //1.4 总价
            totalPrice = totalPrice.add(skuTotalPrice);
            //3.2 购买数量统计
            totalQuantity += quantity;
            GoodsSku goodsSkuUpdate = new GoodsSku();
            goodsSkuUpdate.setId(skuId);
        }
        //1.5、总价设置、创建时间
        shoppingOrder.setTotalPrice(totalPrice);
        LocalDateTime now = LocalDateTime.now();
        shoppingOrder.setCreateTime(now);
        int insert = shoppingOrderMapper.insert(shoppingOrder);
        if (insert <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单创建失败");
        }
        //2.3 设置订单id
        for (ShoppingOrderDetail orderDetail : orderDetails) {
            orderDetail.setOrderId(shoppingOrder.getId());
        }
        //2.4 存入订单详情表
        shoppingOrderDetailService.saveBatch(orderDetails);
        //4 创建订单前置页判断
        Boolean byCart = orderCreateRequest.getByCart();
        if (byCart != null && byCart) {
            //4.1购物车页面下单，删除已下单购物车内的商品数据
            QueryWrapper<ShoppingCart> shoppingCartQueryWrapper = new QueryWrapper<>();
            shoppingCartQueryWrapper.eq("user_id", user.getId()).eq("selected", 1);
            int delete = shoppingCartMapper.delete(shoppingCartQueryWrapper);
            if (delete <= 0) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "购物车数据清除失败，系统错误！");
            }
        }
        //4.2 sku数据库存更新
        //todo 并发要求
        for (GoodsSkuOrderRequest goodsSkuOrderRequest : buyGoodsSkuList) {
            GoodsSku goodsSku = new GoodsSku();
            goodsSku.setId(goodsSkuOrderRequest.getSkuId());
            goodsSku.setStock(goodsSkuOrderRequest.getQuantity());
            Boolean aBoolean = goodsSkuMapper.updateByGoodsSku(goodsSku);
            if (Boolean.FALSE.equals(aBoolean)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "库存更新失败");
            }
        }
        //3.3 返回信息设置
        return getCreateOrderVO(shoppingOrder, totalQuantity, totalPrice);
    }

    /**
     * 返回信息设置
     *
     * @param shoppingOrder 订单信息
     * @param totalQuantity 商品数量
     * @param totalPrice    总价
     * @return createOrderVO
     */
    private CreateOrderVO getCreateOrderVO(ShoppingOrder shoppingOrder, int totalQuantity, BigDecimal totalPrice) {
        CreateOrderVO createOrderVO = new CreateOrderVO();
        createOrderVO.setOrderId(shoppingOrder.getId());
        createOrderVO.setPayType(shoppingOrder.getPayType());
        createOrderVO.setOrderStatus(shoppingOrder.getOrderStatus());
        createOrderVO.setPostage(shoppingOrder.getPostage());
        createOrderVO.setTotalQuantity(totalQuantity);
        createOrderVO.setTotalPrice(shoppingOrder.getTotalPrice());
        createOrderVO.setPayPrice(totalPrice.add(shoppingOrder.getPostage()));
        createOrderVO.setCreateTime(shoppingOrder.getCreateTime());
        createOrderVO.setPayLastTime(shoppingOrder.getCreateTime().plusMinutes(30L));
        return createOrderVO;
    }


    @Override
    public ShoppingOrderVO orderDetail(Long id) {
        UserVO user = UserHolder.getUser();
        ShoppingOrder shoppingOrder = this.getById(id);
        ShoppingOrderVO shoppingOrderVO = this.toShoppingOrderVO(shoppingOrder, user);
        return shoppingOrderVO;

    }


    @Override
    public Page<ShoppingOrderVO> getOrderByStatus(OrderQueryRequest orderQueryRequest) {
        UserVO user = UserHolder.getUser();
        Long userId = user.getId();
        Integer orderStatus = orderQueryRequest.getOrderStatus();
        long current = orderQueryRequest.getCurrent();
        long pageSize = orderQueryRequest.getPageSize();
        if (orderStatus == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "请求参数为null");
        }
        QueryWrapper<ShoppingOrder> queryWrapper = new QueryWrapper<>();
        if(user.getUserPower().equals("0")){
            queryWrapper.eq("user_id", userId);
        }
        queryWrapper.orderBy(true, false, "create_time");
        if (orderStatus != -1) {
            //查询相关状态订单
            queryWrapper.eq("order_status", orderStatus);
        }
        PageDTO<ShoppingOrder> orderRecords = this.page(new PageDTO<>(current, pageSize), queryWrapper);
        List<ShoppingOrder> records = orderRecords.getRecords();
        List<ShoppingOrderVO> shoppingOrderVOS = records.stream()
                .map(shoppingOrder -> {
                    //订单号查询相关 订单详情
                    return this.toShoppingOrderVO(shoppingOrder, user);
                })
                .toList();
        PageDTO<ShoppingOrderVO> goodsBasicVOPageDTO = new PageDTO<>(orderRecords.getCurrent(), orderRecords.getSize(), orderRecords.getTotal());
        goodsBasicVOPageDTO.setRecords(shoppingOrderVOS);
        return goodsBasicVOPageDTO;
    }


    private ShoppingOrderVO toShoppingOrderVO(ShoppingOrder shoppingOrder, UserVO user) {
        ShoppingOrderVO shoppingOrderVO = new ShoppingOrderVO();
        String statusName = stringRedisTemplate.opsForValue().get(STATUS + shoppingOrder.getOrderStatus());
        Map<String, String> integerStringHashMap = new HashMap<>();
        integerStringHashMap.put("status", String.valueOf(shoppingOrder.getOrderStatus()));
        integerStringHashMap.put("statusName", statusName);
        shoppingOrderVO.setOrderId(shoppingOrder.getId());
        shoppingOrderVO.setUserId(user.getId());
        shoppingOrderVO.setTotalPrice(shoppingOrder.getTotalPrice());
        shoppingOrderVO.setReceiverName(shoppingOrder.getReceiverName());
        shoppingOrderVO.setReceiverMobile(shoppingOrder.getReceiverMobile());
        shoppingOrderVO.setReceiverAddress(shoppingOrder.getReceiverAddress());
        shoppingOrderVO.setOrderStatusMap(integerStringHashMap);
        shoppingOrderVO.setPostage(shoppingOrder.getPostage());
        shoppingOrderVO.setPayType(shoppingOrder.getPayType());
        shoppingOrderVO.setDeliveryTime(shoppingOrder.getDeliveryTime());
        shoppingOrderVO.setPayTime(shoppingOrder.getPayTime());
        shoppingOrderVO.setEndTime(shoppingOrder.getEndTime());
        shoppingOrderVO.setCreateTime(shoppingOrder.getCreateTime());
        //可下单时间
        shoppingOrderVO.setPayLastTime(shoppingOrder.getCreateTime().plusMinutes(30L));
        //可下单倒计时(秒数倒计时)
        shoppingOrderVO.setCountDownTime(Duration.between(LocalDateTime.now(), shoppingOrderVO.getPayLastTime()).toSeconds());
        List<ShoppingOrderDetailVO> orderDetailVOS = shoppingOrderDetailService.getShoppingOrderDetailVOS(shoppingOrder.getId());
        shoppingOrderVO.setSkusDetailList(orderDetailVOS);
        return shoppingOrderVO;
    }

    private void checkRequest(OrderCreateRequest orderCreateRequest) {
        Integer payType = orderCreateRequest.getPayType();
        if (payType == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "支付类型不能为空");
        }
        Long addressId = orderCreateRequest.getAddressId();
        if (addressId == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "地址信息不能为空");
        }
        List<GoodsSkuOrderRequest> buyGoodsSkuList = orderCreateRequest.getBuyGoodsSkuList();
        if (CollectionUtils.isEmpty(buyGoodsSkuList)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "商品信息不能为空");
        }
        Integer deliveryTimeType = orderCreateRequest.getDeliveryTimeType();
        if (deliveryTimeType == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "请选择配送时间限制");
        }

    }

//订单统计

    @Override
    public Long getObligationOrder() {
        QueryWrapper<ShoppingOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_status", 1);
        return shoppingOrderMapper.selectCount(queryWrapper);
    }

    @Override
    public Long getDeliverOrder() {
        QueryWrapper<ShoppingOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_status", 2);
        return shoppingOrderMapper.selectCount(queryWrapper);
    }

    @Override
    public Long getSumOrder() {
        return shoppingOrderMapper.selectCount(null);
    }

    @Override
    public Long getDayOrder() {
        QueryWrapper<ShoppingOrder> queryWrapper = new QueryWrapper<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String day = dateFormat.format(new Date());
        try {
            Date start = sdf.parse(day + " 00:00:00");
            Date end = sdf.parse(day + " 23:59:59");
            queryWrapper.ge("create_time", start);
            queryWrapper.lt("create_time", end);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return shoppingOrderMapper.selectCount(queryWrapper);
    }

    @Override
    public List<WeekOrderCountVO> getWeekOrder() {
        String start = past7Days("yyyy-MM-dd");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String end = dateFormat.format(new Date());
        List<WeekOrderCountVO> weekOrderCountVOS = shoppingOrderMapper.selectWeekList(start, end);
        //每天都有数据那就直接返回
        if (weekOrderCountVOS.size() == 7) {
            return weekOrderCountVOS;
        }
        //反之没有数据的天填补0
        List<WeekOrderCountVO> orderCountVOS = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            String finalStart = start;
            List<WeekOrderCountVO> dayData = weekOrderCountVOS.stream().filter(weekOrder -> weekOrder.getPastDay().split(" ")[0].equals(finalStart)).toList();
            if (CollectionUtils.isEmpty(dayData)) {
                WeekOrderCountVO weekOrderCountVO = new WeekOrderCountVO();
                weekOrderCountVO.setOrderTotal(0L);
                weekOrderCountVO.setPastDay(start);
                orderCountVOS.add(weekOrderCountVO);
            } else {
                WeekOrderCountVO weekOrderCountVO = dayData.get(0);
                weekOrderCountVO.setPastDay(weekOrderCountVO.getPastDay().split(" ")[0]);
                orderCountVOS.add(dayData.get(0));
            }
            start = addOneDay("yyyy-MM-dd", start);
        }
        return orderCountVOS;
    }

    @Override
    public Boolean toSendGoods(Long orderId) {
        ShoppingOrder shoppingOrder = this.getById(orderId);
        if(!shoppingOrder.getOrderStatus().equals(2)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"订单状态错误");
        }
        ShoppingOrder order = new ShoppingOrder();
        order.setId(orderId);
        order.setOrderStatus(3);
        order.setDeliveryTime(LocalDateTime.now());
        return this.updateById(order);

    }

    @Override
    public Boolean toGetOrder(Long orderId) {
        ShoppingOrder shoppingOrder = this.getById(orderId);
        if(!shoppingOrder.getOrderStatus().equals(3)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"订单状态错误");
        }
        ShoppingOrder order = new ShoppingOrder();
        order.setId(orderId);
        order.setOrderStatus(4);
        order.setDeliveryTime(LocalDateTime.now());
        return this.updateById(order);
    }

    /**
     * 过去七天时间
     *
     * @param format
     * @return
     */
    public static String past7Days(String format) {
        SimpleDateFormat sd = new SimpleDateFormat(format);
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.DATE, -7);
        Date d = c.getTime();
        return sd.format(d);
    }

    /**
     * 日期加一天
     *
     * @param format
     * @return
     */
    public static String addOneDay(String format, String start) {
        SimpleDateFormat sd = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = sd.parse(start);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DATE, +1);
        Date d = c.getTime();
        return sd.format(d);
    }
}




